package com.itmuch.contentcenter.service.content;

import com.itmuch.contentcenter.dao.content.ShareMapper;
import com.itmuch.contentcenter.dao.messaging.RocketmqTransactionLogMapper;
import com.itmuch.contentcenter.domain.dto.content.ShareAuditDto;
import com.itmuch.contentcenter.domain.dto.content.ShareDto;
import com.itmuch.contentcenter.domain.dto.message.UserAddBonusMsgDto;
import com.itmuch.contentcenter.domain.dto.user.UserDto;
import com.itmuch.contentcenter.domain.entity.content.Share;
import com.itmuch.contentcenter.domain.entity.messaging.RocketmqTransactionLog;
import com.itmuch.contentcenter.domain.enums.AuditStatusEnum;
import java.util.Objects;
import java.util.UUID;

import com.itmuch.contentcenter.feignclient.UserCenterFeignClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

/**
 * @author caiqian
 * @date 2021/5/7 10:16
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class ShareService {

  private final ShareMapper shareMapper;
  private final UserCenterFeignClient userCenterFeignClient;
  private final RocketMQTemplate rocketMQTemplate;
  private final RocketmqTransactionLogMapper rocketmqTransactionLogMapper;


  public ShareDto findById(Integer id) {
    Share share = this.shareMapper.selectByPrimaryKey(id);

    //这里需要获取用户中心的数据,RestTemplate
//    UserDto userDto = this.restTemplate.getForObject(
//        "http://user-center/users/{userid}",
//        UserDto.class,
//        share.getUserId()
//    );

    UserDto userDto = this.userCenterFeignClient.findById(id);

    //消息装配
    ShareDto shareDto = new ShareDto();
    BeanUtils.copyProperties(share, shareDto);

    shareDto.setWxNickname(userDto.getWxNickname());

    return shareDto;
  }

  public static void main(String[] args) {
    RestTemplate restTemplate = new RestTemplate();
    String forObject = restTemplate.getForObject(
        "http://localhost:8081/users/1",
        String.class
    );

    System.out.println(forObject);
  }

  public Share auditById(Integer id, ShareAuditDto auditDto) {
    // 1 查询share是否存在, 不存在或者当前的状态!= NOT_YET,则抛异常
    Share share = this.shareMapper.selectByPrimaryKey(id);

    if (share == null) {
      throw new IllegalArgumentException("参数非法,该分享不存在!");
    }

    if (!Objects.equals("NOT_YET", share.getAuditStatus())) {
      throw new IllegalArgumentException("参数非法,该分享已审核通过或者已拒绝");
    }
    // 2 审核状态,将状态置为Pass/Reject
    share.setAuditStatus(auditDto.getAuditStatusEnum().toString());
    this.shareMapper.updateByPrimaryKey(share);
    // 3 如果是pass,那么为发布人添加积分
    // 可以异步执行, 因为审核是主要操作, 加积分并不是主要的行为
    // 这样可以提高用户体验,不需要等待后面的操作
    // 目前可以使用UserCenterFeignClient 方法来处理

    //改为mq: 如果是pass,那么将消息发送给mq, 让用户中心去消息, 并更新积分信息

//    this.rocketMQTemplate.convertAndSend("add-bonus",
//        MessageBuilder.withPayload(
//            UserAddBonusMsgDto.builder()
//                .userId(share.getUserId())
//                .bonus(50)
//                .build()
//       );

    // 分布式事务改造
    if (AuditStatusEnum.PASS.equals(auditDto.getAuditStatusEnum())) {
      //发送半消息
      String transactionId = UUID.randomUUID().toString();
      this.rocketMQTemplate.sendMessageInTransaction(
          "tx-add-bonus-group",
          "add-bonus",
          MessageBuilder.withPayload(
              UserAddBonusMsgDto.builder()
                  .userId(share.getUserId())
                  .bonus(50)
                  .build()
          )
              //header有妙用
              .setHeader(RocketMQHeaders.TRANSACTION_ID, transactionId)
              .setHeader("share_id", id)
              .build(),
          //arg 有大用处
          auditDto
      );
    } else {
      this.auditByIdInDb(share.getId(), auditDto);
    }

    return share;
  }

  public void auditByIdInDb(Integer shareId, ShareAuditDto auditDto) {
    Share share = Share.builder()
        .id(shareId)
        .auditStatus(auditDto.getAuditStatusEnum().toString())
        .reason(auditDto.getReason())
        .build();

    this.shareMapper.updateByPrimaryKeySelective(share);
  }

  @Transactional(rollbackFor = Exception.class)
  public void auditByIdInDbWithRockMqLog(Integer shareId, ShareAuditDto auditDto,
      String transactionId) {
    this.auditByIdInDb(shareId, auditDto);

    this.rocketmqTransactionLogMapper.insertSelective(
        RocketmqTransactionLog.builder()
            .transactionId(transactionId)
            .log("审核分享!")
            .build()
    );

  }

}
